#ifndef XGE_XATOMIC_OPERATION_H_
#define XGE_XATOMIC_OPERATION_H_

#include "xge_common_config.h"
#include "xallstatic.h"
#include "xassert.h"
#include <windows.h>

namespace xge {

  // some atomic operation wrapper 
  class AtomicOperation:public AllStatic {
  public:
    typedef LONG Atomic_t;
    typedef volatile Atomic_t OperationType;
    typedef volatile Atomic_t* OperationTypePtr;
  public:
    // memory operation
    static void MemoryBarrier(){
      ::MemoryBarrier();
    }
    // this is the atomic operation 
    static Atomic_t AtomicSwap( OperationTypePtr dest , int val ) {
      return (Atomic_t)(InterlockedExchange((volatile LONG*)(dest),val));
    }
    // this is the atomic operation
    static Atomic_t AtomicCAS( OperationTypePtr dest , int val , int cmp ) {
      return (Atomic_t)(InterlockedCompareExchange((volatile LONG*)(dest),val,cmp));
    }
    // inc atomic
    static Atomic_t AtomicIncrement( OperationTypePtr dest ){
      return (Atomic_t)(InterlockedIncrement((volatile LONG*)(dest)));
    }
    // dec atomic
    static Atomic_t AtomicDecrement( OperationTypePtr dest ) {
      return (Atomic_t)(InterlockedDecrement((volatile LONG*)(dest)));
    }
    // strong atomic operation setting
    static void AtomicSet( OperationTypePtr dest , int val ) {
      AtomicSwap(dest,val);
    }
    
    // pause
    static void Pause( size_t tms ) {
      __asm {
        mov eax , tms
L1:
        pause
          add eax , -1
          jne L1
      }
      return ;
    }
  };

  template< typename T > 
  AtomicOperation::Atomic_t LoadAndAcquire( volatile T& dest ) { 
    AtomicOperation::Atomic_t ret = (AtomicOperation::Atomic_t)dest ;  
    AtomicOperation::MemoryBarrier();
    return ret;
  }

  template< typename T >
  AtomicOperation::Atomic_t AcquireAndLoad( volatile T& dest ) {
    return (AtomicOperation::Atomic_t)dest;
  }

  template< typename T >
  void StoreAndRelease( volatile T& loc , const T& val ){
    AtomicOperation::MemoryBarrier();
    loc = val ;
  }

  template< typename T >
  void ReleaseAndStore( volatile T& loc , const T& val ) {
    loc = val;
  }


  // This class provides the basic atomic DWORD ( 4 bytes ) memory operation 
  // stuff 

  namespace xge_internal{
    // We simply doing a wrapper here
    template < class value_type , size_t memory_size > class AtomicImplementation {
    };
    // We just have a 4 byte memory implementation here 
    // since it is enough for our project 
    // this atomic operation ONLY allow set and get value is Atomic 
    // do not provide other operation like add or sub etc 
    // since it is not useful in practise .
    template< class value_type > class AtomicImplementation<value_type,4> {
    private:
      typedef unsigned char byte_t ; // in a c++ IOS , the byte_t == 8 bits
      typedef AtomicImplementation<value_type,4> self_type;
      union ival{
        byte_t   bits[4];    // this is that 4 bits
        value_type value;   // this is our internal memory buffer here
      };
      // a volatile value goes here
      volatile ival val_;
    public: 
       operator value_type() const volatile {
        return LoadAndAcquire(val_.value);
      }
      template< typename T > value_type operator = ( const T& value ) {
        STATIC_ASSERT(sizeof(T) == 4);
        StoreAndRelease(val_.value,value);
      }
      AtomicImplementation( const self_type& another ) {
        LoadAndAcquire(val_.value,another.val_.value);
      }
      template< typename T > AtomicImplementation( const T& value ) {
        *this = value;
      }
      AtomicImplementation(){
        *this=(int)(0);
      }
    };
  }//namespace xge_internal

  // A simple atomic type
  // You can only use this for those 4 byte type
  // like AtomicValue<int> AtomicValue<size_t> etc...
  template< class AtomicType > class AtomicValue : 
  public xge_internal::AtomicImplementation< AtomicType ,sizeof(AtomicType) > {
  };

} // namespace xge


#endif// XGE_XATOMIC_OPERATION_H_